package com.chenyue.cm.api.order;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.chenyue.cm.auth.Login;
import com.chenyue.cm.auth.LoginUser;
import com.chenyue.cm.bean.Success;
import com.chenyue.cm.common.constant.DomainConfig;
import com.chenyue.cm.common.constant.RedisPrefix;
import com.chenyue.cm.exception.SysRuntimeException;
import com.chenyue.cm.order.domain.JdOrder;
import com.chenyue.cm.order.domain.JdProduct;
import com.chenyue.cm.order.domain.JdProductType;
import com.chenyue.cm.pay.ali.AliPayConfig;
import com.chenyue.cm.pay.wx.WXPayUtil;
import com.chenyue.cm.pay.wx.WxConfig;
import com.chenyue.cm.pay.wx.WxPay;
import com.chenyue.cm.pay.wx.WxPayConstants;
import com.chenyue.cm.payment.service.JdOrderService;
import com.chenyue.cm.payment.service.JdProductTypeService;
import com.chenyue.cm.user.domain.JdAppUser;
import com.chenyue.cm.utils.DateUtils;
import com.chenyue.cm.utils.RedisUtils;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.net.URLEncoder;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 * @author libingxing
 * @date 2021-07-05
 */
@Api(tags = "订单管理")
@RestController
@RequestMapping("/api/order")
public class ApiJdOrderController {

    private final JdOrderService jdOrderService;

    private final JdProductTypeService productTypeService;

    private final RedisUtils redisUtils;

    private final WxConfig wxConfig;

    public ApiJdOrderController(JdOrderService jdOrderService, JdProductTypeService productTypeService, RedisUtils redisUtils, WxConfig wxConfig) {
        this.jdOrderService = jdOrderService;
        this.productTypeService = productTypeService;
        this.redisUtils = redisUtils;
        this.wxConfig = wxConfig;
    }

    @GetMapping("/getOrder")
    @ApiOperation("根据订单号查订单")
    public Success<JdOrder> getOrder(
            Integer orderNum
    ) {
        final JdOrder one = jdOrderService.lambdaQuery().eq(JdOrder::getOrderNum, orderNum).one();
        return Success.success(one);
    }

    @Login
    @PostMapping("/createOrder")
    @ApiOperation("创建订单")
    @ApiOperationSupport(order = 1)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "购买数量", name = "buyCount", dataType = "string", required = true),
    })
    public Success<JdOrder> createOrder(
            @ApiParam @RequestBody JdProduct product,
            @RequestParam(defaultValue = "1") Integer buyCount,
            @ApiIgnore @LoginUser JdAppUser user
    ) {
        JdOrder order = jdOrderService.createOrder(product, buyCount, Integer.valueOf(user.getId()));
        return Success.success(order);
    }

    @Login
    @PostMapping("/wxGenerateOrder")
    @ApiOperation("创建微信订单")
    @ApiOperationSupport(order = 1)
    public Success<Map<String, String>> wxGenerateOrder(
            @ApiParam @RequestBody JdOrder order
    ) throws Exception {
        //        微信统一下单
        Map<String, String> param = new HashMap<>(10);
        Map<String, String> newSign = new HashMap<>(10);

        String notifyUrl = DomainConfig.LOCALHOST + "/CM/" + "api/account/wxRecharge";
        JdProductType type = getProductType(order.getId());
        param.put("body", type.getName());
        param.put("total_fee", Math.round(order.getProductPrice() * 100) + "");
        WxPay wxPay = new WxPay(wxConfig, notifyUrl);
        param.put("out_trade_no", order.getId() + "");
        param.put("attach", order.getUserId() + "");
        Map<String, String> result = wxPay.unifiedOrder(param);
//        订单签名
        if (WxPayConstants.FAIL.equals(result.get("return_code"))) {
            return Success.error(result.get("return_msg"));
        }
        newSign.put("package", "Sign=WXPay");
        newSign.put("appid", wxConfig.getAppId());
        newSign.put("partnerid", wxConfig.getMchId());
        newSign.put("prepayid", result.get("prepay_id"));
        newSign.put("noncestr", result.get("nonce_str"));
        newSign.put("timestamp", System.currentTimeMillis() / 1000 + "");
        String sign = WXPayUtil.generateSignature(newSign, wxConfig.getKey());
        newSign.put("sign", sign);
        return Success.success(newSign);
    }

    @Login
    @PostMapping("/aliGenerateOrder")
    @ApiOperation("阿里创建订单")
    @ApiOperationSupport(order = 1)
    public Success<String> aliGenerateOrder(
            @ApiParam @RequestBody JdOrder order
    ) throws Exception {
//        设置请求网关 (gateway)、应用 id (app_id)、应用私钥 (private_key)、编码格式 (charset)、支付宝公钥 (alipay_public_key)、签名类型 (sign_type)即可，报文请求时会自动进行签名。
        AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.URL, AliPayConfig.APP_ID, AliPayConfig.RSA_PRIVATE_KEY, AliPayConfig.FORMAT, AliPayConfig.CHARSET, AliPayConfig.ALIPAY_PUBLIC_KEY, AliPayConfig.SIGNTYPE);
        AlipayTradeAppPayRequest requestParam = new AlipayTradeAppPayRequest();
//        构建订单模型
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
//        订单价格
        model.setTotalAmount(order.getOrderAmount() + "");
//        商品类型名称
        JdProductType type = getProductType(order.getId());
        model.setSubject(type.getName());
//        订单号
        model.setOutTradeNo(order.getOrderNum());
//        0虚拟 1实物
        model.setGoodsType("0");
//        自定义参数  URLEncoder用于防止传输乱码
        model.setPassbackParams(URLEncoder.encode(order.getId() + "", "utf-8"));
//        订单有效期
        model.setTimeExpire(DateUtil.format(DateUtil.offsetMinute(Calendar.getInstance().getTime(), 30), DateUtils.DEFAULT_DATETIME_FORMAT));
        model.setTotalAmount(order.getProductPrice() + "");
//        页面跳转异步通知页面路径
        requestParam.setNotifyUrl(DomainConfig.LOCALHOST + "/CM/" + "api/account/aliRecharge");
//        配置model
        requestParam.setBizModel(model);
        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(requestParam);
        if (response.isSuccess()) {
            return Success.success("操作成功", response.getBody());
        } else {
            return Success.error(500, response.getMsg(), response.getBody());
        }
    }

    /**
     * 根据orderId 获取redis临时订单数据
     *
     * @param orderId 订单id
     * @return 商品类型
     */
    private JdProductType getProductType(Integer orderId) {
        final JSONObject order = redisUtils.get(RedisPrefix.TEMP_ORDER + orderId, JSONObject.class);

        JdProductType type = productTypeService.lambdaQuery()
                .eq(JdProductType::getId, order.getIntValue("type"))
                .one();
        if (type == null) {
            throw new SysRuntimeException("当前商品存在异常，无法创建订单！");
        }
        return type;
    }

}
